package cn.edu.jxust.core.infrastructure.util;

import cn.edu.jxust.core.infrastructure.util.location.AddressDetails;
import cn.edu.jxust.core.infrastructure.util.location.LngAndLat;
import cn.edu.jxust.core.infrastructure.util.location.Location;
import cn.edu.jxust.core.infrastructure.util.location.LocationResult;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

/**
 * @author QiuKangming
 * @version 1.0
 * @description 地理位置工具类, 根据地址信息转换成经纬度对象, 根据经纬度转换成地址对象
 * @since 2020/07/07 15:48
 */
@Slf4j
@SuppressWarnings("unused")
public class LocationUtils {

    /**
     * 百度应用AK码
     */
    private static final String AK = "dTaqSB02CSumty3vQLoHDYzGd7uGdyGk";

    /**
     * 根据地址获取经纬度
     * @param address 地址
     * @return LngAndLat
     */
    public static LngAndLat getLngAndLat(String address){

        String url = "http://api.map.baidu.com/geocoding/v3/?address="+address+"&output=json&ak=" + AK;
        String json = loadJSON(url);
        LocationResult result = JSONUtil.toBean(json, LocationResult.class);
        Object obj = result.getResult();
        return JSONUtil.toBean(obj.toString(), LngAndLat.class);

    }

    /**
     * 根据经纬度获取详细地址
     * @param location 地理位置
     * @return AddressDetails
     */
    public static AddressDetails getAddressDetails(Location location){

        String json = loadJSON("http://api.map.baidu.com/reverse_geocoding/v3/?ak=" + AK + "&output=json&coordtype=wgs84ll&location=" + location.getLat() + "," + location.getLng());
        LocationResult result = JSONUtil.toBean(json, LocationResult.class);
        Object obj = result.getResult();
        return JSONUtil.toBean(obj.toString(), AddressDetails.class);

    }

    /**
     * 加载 JSON 字符串
     * @param url 网址
     * @return String
     */
    private static String loadJSON(String url) {

        StringBuilder json = new StringBuilder();
        try {
            URL oracle = new URL(url);
            URLConnection yc = oracle.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                json.append(inputLine);
            }
            in.close();
        } catch (Exception e) {
            log.error("LocationUtils --> loadJSON: {}", e.getMessage());
        }
        return json.toString();

    }

    /**
     * 国测局坐标(火星坐标, GCJ-02) -> 百度坐标(BD-09)
     * @param lng 经度
     * @param lat 纬度
     * @return double[]
     */
    public static double[] mars2Baidu(double lng, double lat){

        double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * Math.PI * 3000D / 180D);
        double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * Math.PI * 3000D / 180D);

        double longitude = z * Math.cos(theta) + 0.0065;
        double latitude = z * Math.sin(theta) + 0.006;
        return new double[] {longitude, latitude};

    }

    /**
     * 百度坐标(BD-09) -> 国测局坐标(火星坐标, GCJ-02)
     * @param lng 经度
     * @param lat 纬度
     * @return double[]
     */
    public static double[] baidu2Mars(double lng, double lat){

        double x = lng - 0.0065;
        double y = lat - 0.006;

        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI * 3000D / 180D);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI * 3000D / 180D);

        double longitude = z * Math.cos(theta);
        double latitude = z * Math.sin(theta);
        return new double[] { longitude, latitude };

    }

}
